Skip to content

Implement type completeness exemptions in type hint analyzer - #1276

Closed
bact with Copilot wants to merge 11 commits into
devfrom
copilot/update-type-hint-analyzer
Closed

Implement type completeness exemptions in type hint analyzer#1276
bact with Copilot wants to merge 11 commits into
devfrom
copilot/update-type-hint-analyzer

Conversation

Copilot AI commented Feb 4, 2026

Copy link
Copy Markdown
Contributor

What do these changes do

Implements exemptions from Python typing documentation's type completeness guidelines in the type hint analyzer.

What was wrong

The analyzer flagged legitimate cases that don't require type annotations per PEP 561:

  • Constants with simple literals (MAX_VALUE = 100)
  • Enum values
  • Type aliases without explicit TypeAlias annotation
  • __init__ return types
  • Special module symbols (__all__, __version__, etc.)
  • Special class symbols (__slots__, __dict__, etc.)

Additionally, the type alias detection was too broad, incorrectly exempting:

  • Value subscripts like VALUE = mapping["key"]
  • Bitwise flag operations like FLAGS = FLAG_A | FLAG_B or MASK = 1 | 2

How this fixes it

Detection methods added:

  • _is_exempt_module_symbol() / _is_exempt_class_symbol() - special dunders
  • _is_simple_literal() - only str/int/float/bool/None (excludes bytes, ellipsis)
  • _is_constant_name() - ALL_CAPS including private (_MAX_VALUE)
  • _is_in_enum_class() - base class tracking
  • _looks_like_type_expr() - distinguishes type expressions from value expressions
  • _is_type_alias_without_annotation() - conservative pattern matching with proper type/value distinction

Core logic updates:

  • check_function_type_hints() - exempts __init__ return types
  • visit_Assign() - skips all exempt variables before flagging
  • visit_ClassDef() - tracks base classes for Enum detection
  • _is_type_alias_without_annotation() - validates subscript bases are known types and checks both operands of | expressions to distinguish type unions (int | str) from bitwise operations (FLAG_A | FLAG_B)
  • _looks_like_type_expr() - checks if expressions look like types (built-in types, typing keywords, None constant, PEP 585 types) to prevent false positives

Optimizations:

  • Module-level constants (_NONE_TYPE, _TYPE_ALIAS_KEYWORDS) avoid repeated computations
  • Deprecated AST nodes (ast.Num, ast.Str) replaced with ast.Constant

Code cleanup based on review:

  • Removed unused _has_final_annotation() helper method
  • Removed unused target parameter from _is_type_alias_without_annotation()
  • Removed dead code check for None in _is_simple_literal()
  • Fixed documentation to accurately reflect that constant exemption is based on ALL_CAPS naming + simple literal check only (does not consult Final annotations)
  • Improved type alias detection to distinguish between:
    • Type subscripts (list[str]) vs value subscripts (mapping["key"])
    • Type unions (int | str, list[str] | None) vs bitwise operations (FLAG_A | FLAG_B, 1 | 2)

Results:

  • 82 fewer false positives (387 vs 469 module variables flagged)
  • All functions now 100% complete (due to __init__ exemption)
  • Accurate type alias detection prevents misclassification of value subscripts and bitwise operations
  • Documentation updated in README.md with accurate exemption details

Your checklist for this pull request

  • Passed code styles and structures
  • Passed code linting checks and unit test
Original prompt

Update this type hint analyser script build_tools/analysis/type_hint_analyzer.py
to take the facts from https://typing.python.org/en/latest/guides/libraries.html#type-completeness :

Type Completeness

The following are best practice recommendations for how to define “type complete”:

Classes:

  • All class variables, instance variables, and methods that are “visible” (not overridden) are annotated and refer to known types
  • If a class is a subclass of a generic class, type arguments are provided for each generic type parameter, and these type arguments are known types

Functions and Methods:

  • All input parameters have type annotations that refer to known types
  • The return parameter is annotated and refers to a known type
  • The result of applying one or more decorators results in a known type

Type Aliases:

  • All of the types referenced by the type alias are known

Variables:

  • All variables have type annotations that refer to known types

Type annotations can be omitted in a few specific cases where the type is obvious from the context:

  • Constants that are assigned simple literal values (e.g. RED = '#F00' or MAX_TIMEOUT = 50 or room_temperature: Final = 20). A constant is a symbol that is assigned only once and is either annotated with Final or is named in all-caps. A constant that is not assigned a simple literal value requires explicit annotations, preferably with a Final annotation (e.g. WOODWINDS: Final[list[str]] = ['Oboe', 'Bassoon']).
  • Enum values within an Enum class do not require annotations because they take on the type of the Enum class.
  • Type aliases do not require annotations. A type alias is a symbol that is defined at a module level with a single assignment where the assigned value is an instantiable type, as opposed to a class instance (e.g. Foo = Callable[[Literal["a", "b"]], int | str] or Bar = MyGenericClass[int] | None).
  • The “self” parameter in an instance method and the “cls” parameter in a class method do not require an explicit annotation.
  • The return type for an init method does not need to be specified, since it is always None.
  • The following module-level symbols do not require type annotations: all,author, copyright, email, license, title, uri, version.
  • The following class-level symbols do not require type annotations: class, dict, doc, module, slots.

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 4 commits February 4, 2026 09:14
Co-authored-by: bact <128572+bact@users.noreply.github.com>
Co-authored-by: bact <128572+bact@users.noreply.github.com>
Co-authored-by: bact <128572+bact@users.noreply.github.com>
…ndant calls

Co-authored-by: bact <128572+bact@users.noreply.github.com>
@bact bact added the infrastructure build process, configuration, GitHub Actions label Feb 4, 2026
Copilot AI and others added 3 commits February 4, 2026 09:21
Co-authored-by: bact <128572+bact@users.noreply.github.com>
Co-authored-by: bact <128572+bact@users.noreply.github.com>
Co-authored-by: bact <128572+bact@users.noreply.github.com>
Copilot AI changed the title [WIP] Update type hint analyzer script for type completeness Implement type completeness exemptions in type hint analyzer Feb 4, 2026
Copilot AI requested a review from bact February 4, 2026 09:26
@bact
bact marked this pull request as ready for review February 4, 2026 09:37
@bact
bact requested a review from Copilot February 4, 2026 09:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refines the type hint analyzer so that it aligns with the Python typing “type completeness” guidance by ignoring several categories of symbols that do not require annotations, and documents these behaviors. It reduces noise from false positives while keeping the reporting and documentation consistent with the new exemption rules.

Changes:

  • Added exemption logic in TypeHintAnalyzer for simple-literal constants, Enum members, implicit type aliases, special module/class dunders, and __init__ return types, plus supporting helpers and state tracking (e.g., Enum base detection).
  • Updated function analysis to treat __init__ return types as implicitly complete and extended result metadata to track whether a return annotation is present.
  • Expanded build_tools/analysis/README.md to describe the new exemption rules and how they affect function, variable, and type-alias analysis.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
build_tools/analysis/type_hint_analyzer.py Implements the exemption rules in the analyzer, including helper methods for exempt symbols, constant detection, enum-class detection, and type-alias pattern detection, and updates function classification logic and minor lint-related annotations.
build_tools/analysis/README.md Documents the analyzer’s exemption behavior and clarifies how functions, variables, enums, and type aliases are classified under the updated rules.

Comment thread build_tools/analysis/type_hint_analyzer.py
Comment thread build_tools/analysis/type_hint_analyzer.py Outdated
Comment thread build_tools/analysis/type_hint_analyzer.py Outdated
Comment thread build_tools/analysis/README.md Outdated
@bact

bact commented Feb 4, 2026

Copy link
Copy Markdown
Member

@copilot apply changes based on the comments in this thread

Co-authored-by: bact <128572+bact@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Comment thread build_tools/analysis/type_hint_analyzer.py Outdated
Comment thread build_tools/analysis/type_hint_analyzer.py
@bact

bact commented Feb 4, 2026

Copy link
Copy Markdown
Member

@copilot apply changes based on the comments in this thread

Co-authored-by: bact <128572+bact@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment on lines +376 to +378
# 2. Union types with | operator (Python 3.10+)
if isinstance(value, ast.BinOp) and isinstance(value.op, ast.BitOr):
return True

Copilot AI Feb 4, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The BinOp check here treats any | expression as a type-alias-like union, which will incorrectly exempt non-type assignments such as bitwise flag combinations (e.g., FLAGS = FLAG_A | FLAG_B or MASK = 1 | 2) from annotation requirements. To avoid these false positives, this branch should distinguish type unions from value-level bitwise ORs (for example by requiring that both operands look like type expressions or come from typing/typing_extensions) before treating the assignment as a type alias.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed by adding a _looks_like_type_expr() helper that checks if both operands of the | operator are type expressions. Now correctly distinguishes type unions (int | str, list[str] | None) from bitwise flag operations (FLAG_A | FLAG_B, 1 | 2). (commit 6d9e3d4)

@bact

bact commented Feb 4, 2026

Copy link
Copy Markdown
Member

@copilot apply changes based on the comments in this thread

Co-authored-by: bact <128572+bact@users.noreply.github.com>
@sonarqubecloud

sonarqubecloud Bot commented Feb 4, 2026

Copy link
Copy Markdown

@bact bact closed this Feb 4, 2026
@bact
bact deleted the copilot/update-type-hint-analyzer branch March 10, 2026 06:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

infrastructure build process, configuration, GitHub Actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants